package com.zondy.mapgis.psmap.manager.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zondy.mapgis.common.core.exception.ServiceException;
import com.zondy.mapgis.common.core.utils.StringUtils;
import com.zondy.mapgis.common.security.utils.SecurityUtils;
import com.zondy.mapgis.domain.psmap.AppDistrict;
import com.zondy.mapgis.domain.psmap.AppDistrictGeoJSONDto;
import com.zondy.mapgis.psmap.manager.mapper.AppDistrictMapper;
import com.zondy.mapgis.psmap.manager.service.IAppDistrictService;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.*;

@Service
public class AppDistrictServiceImpl extends ServiceImpl<AppDistrictMapper, AppDistrict> implements IAppDistrictService {
   private static final Logger log = LoggerFactory.getLogger(AppDistrictServiceImpl.class);
   @Autowired
   private AppDistrictMapper appDistrictMapper;

   @Override
   public AppDistrict selectAppDistrictByDistrictId(Long districtId) {
      return this.appDistrictMapper.selectAppDistrictByDistrictId(districtId);
   }

   @Override
   public List<AppDistrict> selectAppDistrictList(AppDistrict appDistrict) {
      return this.appDistrictMapper.selectAppDistrictList(appDistrict);
   }

   @Override
   public HashMap<Integer, Object> buildDistrictList(Integer year, Integer level, Boolean includeGeoJson) {
      HashMap<Integer, Object> map = new HashMap<>();
      List<Integer> allYears = this.getAllYears();
      List<AppDistrict> all = this.getListByYear(year);
      if (Boolean.FALSE.equals(includeGeoJson)) {

          for (AppDistrict appDistrict : all) {
              appDistrict.setGeoJson(null);
          }
      }

      try {
         List<AppDistrict> districtInfoTreeList;
         if (year != null) {
            districtInfoTreeList = this.buildDistrictTree(all);
            map.put(year, districtInfoTreeList);
         } else {

             for (Integer allYear : allYears) {
                 List<AppDistrict> oneYearList = new ArrayList<>();

                 for (AppDistrict district : all) {
                     if (district != null && district.getYear() != null && district.getYear().equals(allYear)) {
                         oneYearList.add(district);
                     }
                 }

                 districtInfoTreeList = this.buildDistrictTree(oneYearList);
                 map.put(allYear, districtInfoTreeList);
             }
         }

         return map;
      } catch (Exception var13) {
         log.error("获取行政区划信息列表出现异常{}", var13.getMessage());
         return map;
      }
   }

   @Override
   public int insertAppDistrict(AppDistrict appDistrict) {
      appDistrict.setCreateBy(SecurityUtils.getUsername());
      return this.appDistrictMapper.insertAppDistrict(appDistrict);
   }

   @Override
   public int updateAppDistrict(AppDistrict appDistrict) {
      appDistrict.setUpdateBy(SecurityUtils.getUsername());
      return this.appDistrictMapper.updateAppDistrict(appDistrict);
   }

   @Override
   public boolean updateAppDistricts(List<AppDistrict> appDistricts) {
      try {
         List<AppDistrict> existDistricts = this.selectAppDistrictList(new AppDistrict());
         String year = this.getCurrentYear();

          for (AppDistrict district : appDistricts) {
              if (district.getYear() == null) {
                  district.setYear(Integer.parseInt(year));
              }

              if (!this.isDistrictExist(existDistricts, district)) {
                  this.insertAppDistrict(district);
              } else {
                  this.updateAppDistrict(district);
              }
          }

         return true;
      } catch (Exception var6) {
         throw new ServiceException(var6.getMessage());
      }
   }

   @Override
   public int updateGeoJSON(AppDistrictGeoJSONDto resources) {
      AppDistrict district = new AppDistrict();
      district.setYear(Integer.valueOf(resources.getYear()));
      district.setLevel(Integer.valueOf(resources.getLevel()));
      district.setCode(resources.getCode());
      List<AppDistrict> appDistricts = this.appDistrictMapper.selectAppDistrictList(district);
      if (!appDistricts.isEmpty()) {
         AppDistrict appDistrict = appDistricts.get(0);
         appDistrict.setGeoJson(resources.getGeoJson());
         return this.updateAppDistrict(appDistrict);
      } else {
         return 0;
      }
   }

   @Override
   public int deleteAppDistrictByDistrictIds(Long[] districtIds) {
      return this.appDistrictMapper.deleteAppDistrictByDistrictIds(districtIds);
   }

   @Override
   public int deleteAppDistrictByDistrictId(Long districtId) {
      return this.appDistrictMapper.deleteAppDistrictByDistrictId(districtId);
   }

   @Override
   public int importExcel(MultipartFile file) {
      String fileName = file.getOriginalFilename();

      try {
         InputStream stream = file.getInputStream();
         if (fileName != null) {
            Workbook workbook;
            if (fileName.endsWith(".xlsx")) {
               workbook = new XSSFWorkbook(stream);
            } else {
               if (!fileName.endsWith(".xls")) {
                  log.error("不是excel文件");
                  return 0;
               }

               workbook = new HSSFWorkbook(stream);
            }

            Sheet sheet = workbook.getSheetAt(0);
            Row headerRow = sheet.getRow(0);
            int cellCount = headerRow.getLastCellNum();
            int rowCount = sheet.getLastRowNum();
            if (cellCount <= 0) {
               log.error("excel文件不符合规范");
               return 0;
            }

            List<String> headList = new ArrayList<>();

            String year;
            for(int i = headerRow.getFirstCellNum(); i < cellCount; ++i) {
               year = headerRow.getCell(i).getStringCellValue();
               headList.add(year);
            }

            year = this.getCurrentYear();

            for(int j = 1; j <= rowCount; ++j) {
               Row row = sheet.getRow(j);
               int fieldCount = headList.size();
               AppDistrict district = new AppDistrict();

               for(int t = 0; t < fieldCount; ++t) {
                  Cell cell = row.getCell(t);
                  if (cell != null) {
                     String value = cell.toString();
                     if (StringUtils.isNotEmpty(value)) {
                        int i = value.lastIndexOf(".0");
                        if (i >= 0) {
                           value = value.substring(0, i);
                        }
                     }

                     switch (headList.get(t)) {
                        case "代码":
                           district.setCode(value);
                           break;
                        case "代码名称":
                           district.setName(value);
                           break;
                        case "年度":
                           district.setYear(value == null ? null : Integer.parseInt(value));
                           break;
                        case "级别":
                           district.setLevel(value == null ? null : Integer.parseInt(value));
                           break;
                        case "范围":
                           district.setBound(value);
                           break;
                        case "label点":
                           district.setLabelPoint(value);
                     }
                  }
               }

               if (district.getYear() == null) {
                  district.setYear(Integer.parseInt(year));
               }

               if (district.getCode() == null || district.getName() == null) {
                  log.error("excel文件不符合规范");
                  return 0;
               }

               AppDistrict district1 = new AppDistrict();
               district1.setCode(district.getCode());
               district1.setYear(district.getYear());
               district1.setLevel(district.getLevel());
               List<AppDistrict> exists = this.selectAppDistrictList(district1);
               if (!exists.isEmpty()) {
                  AppDistrict exist = exists.get(0);
                  exist.setBound(district.getBound());
                  exist.setLabelPoint(district.getLabelPoint());
                  this.updateAppDistrict(exist);
               } else {
                  this.insertAppDistrict(district);
               }
            }
         }

         return 1;
      } catch (IOException var20) {
         log.error("文件读取出现问题:{}", var20.getMessage());
         return 0;
      }
   }

   private String getCurrentYear() {
      SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
      Date date = new Date();
      return sdf.format(date);
   }

   private boolean isDistrictExist(List<AppDistrict> existDistricts, AppDistrict district) {
      Iterator<AppDistrict> var3 = existDistricts.iterator();

      AppDistrict existDistrict;
      do {
         if (!var3.hasNext()) {
            return false;
         }

         existDistrict = var3.next();
      } while(!existDistrict.getCode().equals(district.getCode()) || !existDistrict.getName().equals(district.getName()) || !existDistrict.getLevel().equals(district.getLevel()) || !existDistrict.getYear().equals(district.getYear()));

      return true;
   }

   public List<Integer> getAllYears() {
      return this.appDistrictMapper.getAllYears();
   }

   public List<AppDistrict> getListByYear(Integer year) {
      AppDistrict appDistrict = new AppDistrict();
      appDistrict.setYear(year);
      return this.appDistrictMapper.selectAppDistrictList(appDistrict);
   }

   public List<AppDistrict> buildDistrictTree(List<AppDistrict> oneYearList) {
      List<AppDistrict> list = new ArrayList<>();
      Set<Integer> set = new HashSet<>();

       for (AppDistrict appDistrict : oneYearList) {
           if (appDistrict.getLevel() != null) {
               set.add(appDistrict.getLevel());
           }
       }

      List<Integer> levelList = new ArrayList<>(set);
      levelList.sort(Comparator.comparingInt((o) -> o));
      Integer minLevel = levelList.get(0);

      for(int m = 0; m < oneYearList.size(); ++m) {
         AppDistrict district = oneYearList.get(m);
         if (district.getLevel().equals(minLevel)) {
            String code = "";
            switch (minLevel) {
               case 1:
               default:
                  break;
               case 2:
                  code = district.getCode().substring(0, 2);
                  break;
               case 3:
                  code = district.getCode().substring(0, 4);
                  break;
               case 4:
                  code = district.getCode().substring(0, 6);
                  break;
               case 5:
                  code = district.getCode().substring(0, 9);
                  break;
               case 6:
                  code = district.getCode().substring(0, 12);
            }

            district.setChildren(this.createTreeChildren(oneYearList, minLevel, code, levelList, district));
            list.add(district);
         }
      }

      return list;
   }

   public List<AppDistrict> createTreeChildren(List<AppDistrict> oneYearList, Integer level, String regionCode, List<Integer> levelList, AppDistrict parentDistrict) {
      List<AppDistrict> children = new ArrayList<>();
      if (level == null) {
         return children;
      } else {
         int bigLevel = 0;

          for (Integer integer : levelList) {
              if (integer > level) {
                  bigLevel = integer;
                  break;
              }
          }

         if (bigLevel == 0) {
            return children;
         } else {
            for(int m = 0; m < oneYearList.size(); ++m) {
               AppDistrict district = oneYearList.get(m);
               String _regionCode;
               switch (bigLevel) {
                  case 1:
                  default:
                     break;
                  case 2:
                     if (bigLevel == district.getLevel() && !StringUtils.isEmpty(district.getCode()) && district.getCode().length() >= 2) {
                        _regionCode = district.getCode().substring(0, 2);
                        district.setChildren(this.createTreeChildren(oneYearList, district.getLevel(), _regionCode, levelList, district));
                        if (district.getChildren() != null && !district.getChildren().isEmpty()) {
                           district.setState("closed");
                        }

                        children.add(district);
                     }
                     break;
                  case 3:
                     if (!StringUtils.isEmpty(district.getCode()) && district.getCode().length() >= 4 && bigLevel == district.getLevel() && this.getCodeByDistrict(parentDistrict.getLevel(), district).equals(regionCode)) {
                        _regionCode = district.getCode().substring(0, 4);
                        district.setChildren(this.createTreeChildren(oneYearList, district.getLevel(), _regionCode, levelList, district));
                        if (district.getChildren() != null && !district.getChildren().isEmpty()) {
                           district.setState("closed");
                        }

                        children.add(district);
                     }
                     break;
                  case 4:
                     if (!StringUtils.isEmpty(district.getCode()) && district.getCode().length() >= 6 && bigLevel == district.getLevel() && this.getCodeByDistrict(parentDistrict.getLevel(), district).equals(regionCode)) {
                        _regionCode = district.getCode().substring(0, 6);
                        district.setChildren(this.createTreeChildren(oneYearList, district.getLevel(), _regionCode, levelList, district));
                        if (district.getChildren() != null && !district.getChildren().isEmpty()) {
                           district.setState("closed");
                        }

                        children.add(district);
                     }
                     break;
                  case 5:
                     if (!StringUtils.isEmpty(district.getCode()) && district.getCode().length() >= 9 && bigLevel == district.getLevel() && this.getCodeByDistrict(parentDistrict.getLevel(), district).equals(regionCode)) {
                        _regionCode = district.getCode().substring(0, 9);
                        district.setChildren(this.createTreeChildren(oneYearList, district.getLevel(), _regionCode, levelList, district));
                        if (district.getChildren() != null && !district.getChildren().isEmpty()) {
                           district.setState("closed");
                        }

                        children.add(district);
                     }
                     break;
                  case 6:
                     if (!StringUtils.isEmpty(district.getCode()) && district.getCode().length() >= 9 && bigLevel == district.getLevel() && this.getCodeByDistrict(parentDistrict.getLevel(), district).equals(regionCode)) {
                        children.add(district);
                     }
               }
            }

            return children;
         }
      }
   }

   public String getCodeByDistrict(Integer level, AppDistrict district) {
      if (!StringUtils.isEmpty(district.getCode()) && !district.getCode().isEmpty()) {
          return switch (level) {
              case 2 -> district.getCode().substring(0, 2);
              case 3 -> district.getCode().substring(0, 4);
              case 4 -> district.getCode().substring(0, 6);
              case 5 -> district.getCode().substring(0, 9);
              case 6 -> district.getCode().substring(0, 12);
              default -> "";
          };
      } else {
         return "";
      }
   }
}
